package com.aicode;

import com.aicode.proto.CommonProto;
import com.aicode.proto.LoginProto;
import com.google.protobuf.GeneratedMessageV3;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.MessageToByteEncoder;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
import io.netty.handler.codec.protobuf.ProtobufEncoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.stream.ChunkedWriteHandler;

import java.util.List;

public class TestServer {

    public static void main(String[] args) {
        // 启动TCP服务器
        new Thread(() -> startTcpServer(9090)).start();
        
        // 启动WebSocket服务器
      //  new Thread(() -> startWebSocketServer(8081)).start();
    }

    private static void startTcpServer(int port) {
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    .handler(new LoggingHandler(LogLevel.INFO))
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();
                            // 添加自定义编解码器处理GameMsg对象
                            pipeline.addLast(new GameMsgDecoder());
                            pipeline.addLast(new GameMsgEncoder());
                            // 添加业务处理handler
                            pipeline.addLast(new ServerHandler());
                        }
                    });

            ChannelFuture future = bootstrap.bind(port).sync();
            System.out.println("TCP Server started on port " + port);
            future.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    private static void startWebSocketServer(int port) {
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    .handler(new LoggingHandler(LogLevel.INFO))
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();
                            
                            // 添加HTTP编解码器
                            pipeline.addLast(new HttpServerCodec());
                            pipeline.addLast(new ChunkedWriteHandler());
                            pipeline.addLast(new HttpObjectAggregator(8192));
                            
                            // 添加WebSocket支持
                            pipeline.addLast(new WebSocketServerProtocolHandler("/websocket"));
                            
                            // 添加ProtoBuf编解码器
                            pipeline.addLast(new ProtobufVarint32FrameDecoder());
                            // 注释掉固定的proto对象，允许动态转换
                            // pipeline.addLast(new ProtobufDecoder(YourProtoClass.getDefaultInstance()));
                            pipeline.addLast(new ProtobufVarint32LengthFieldPrepender());
                            pipeline.addLast(new ProtobufEncoder());
                            
                            // 添加自定义编解码器处理GameMsg对象
                            pipeline.addLast(new GameMsgDecoder());
                            pipeline.addLast(new GameMsgEncoder());
                            
                            // 添加业务处理handler
                            pipeline.addLast(new WebSocketServerHandler());
                        }
                    });

            ChannelFuture future = bootstrap.bind(port).sync();
            System.out.println("WebSocket Server started on port " + port);
            future.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
    
    // 自定义GameMsg解码器
    static class GameMsgDecoder extends ByteToMessageDecoder {
        @Override
        protected void decode(ChannelHandlerContext ctx, ByteBuf byteBuf, List<Object> list) throws Exception {
            if(byteBuf.readableBytes() < 8){
                return;
            }
            byteBuf.markReaderIndex();
            int bodyLength = byteBuf.readInt();
            if(bodyLength > 1024 * 1024* 10){
                ctx.close();
                return;
            }
            if(byteBuf.readableBytes() < bodyLength + 4){
                byteBuf.resetReaderIndex();
                return;
            }
            int command = byteBuf.readInt();
            byte[] body = null;
            if(bodyLength > 0){
                body = new byte[bodyLength];
                byteBuf.readBytes(body);
            }
            GameMsg gameMsg = new GameMsg();
            gameMsg.setCommand(command);
            gameMsg.setData(body);
            list.add(gameMsg);
        }
    }
    
    // 自定义GameMsg编码器
    static class GameMsgEncoder extends MessageToByteEncoder<GameMsg> {

        @Override
        protected void encode(ChannelHandlerContext channelHandlerContext, GameMsg gameMsg, ByteBuf byteBuf) throws Exception {
            byte[] array = gameMsg.getData();
            int length = 0;
            if (array != null) {
                length = array.length;
            }
            byteBuf.writeInt(length);
            int command = gameMsg.getCommand();
            byteBuf.writeInt(command);
            if(length > 0){
                byteBuf.writeBytes(array);
            }
        }
    }
    
    // TCP连接处理器 - 修改为处理GameMsg对象
    static class ServerHandler extends SimpleChannelInboundHandler<GameMsg> {


        @Override
        protected void channelRead0(ChannelHandlerContext ctx, GameMsg gameMsg) throws Exception {
            System.out.println("channelRead0 command="+gameMsg.getCommand());
            if(gameMsg.getCommand() == 1001){
                LoginProto.LoginReq login = LoginProto.LoginReq.parseFrom(gameMsg.getData());

                LoginProto.LoginRes.Builder builder = LoginProto.LoginRes.newBuilder();
                builder.setErrorCode(buildErrorCode(CommonProto.ErrorCode.SUCCESS_VALUE,""));
                builder.setRoleId(System.currentTimeMillis());
                builder.setUserId(login.getUserId());
                builder.setName("测试");
                writeGameMsg(ctx.channel(),1001,builder.build());
            }
            else if(gameMsg.getCommand() == 1){
                LoginProto.HeartbeatReq heartbeatReq = LoginProto.HeartbeatReq.parseFrom(gameMsg.getData());
                System.out.println("收到心跳");
                LoginProto.HeartbeatRes.Builder builder = LoginProto.HeartbeatRes.newBuilder();
                builder.setErrorCode(com.aicode.proto.CommonProto.DynamicErrorCode.newBuilder().setCode(0).build());
                builder.setStime(System.currentTimeMillis());
                writeGameMsg(ctx.channel(),1,builder.build());
            }
            else if(gameMsg.getCommand() == 1002){
                LoginProto.TestGMReq testGMReq = LoginProto.TestGMReq.parseFrom(gameMsg.getData());
                System.out.println("收到GM指令："+testGMReq.getGm());
                LoginProto.TestGMRes.Builder builder = LoginProto.TestGMRes.newBuilder();
                builder.setErrorCode(buildErrorCode(CommonProto.ErrorCode.SUCCESS_VALUE,""));
                builder.setResult("GM指令执行成功"+System.currentTimeMillis());
                writeGameMsg(ctx.channel(),1002,builder.build());
            }
            else{
                System.out.println("未知的命令："+gameMsg.getCommand());
            }

        }

        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
            System.out.println(cause.getMessage());
            cause.printStackTrace();
        }
    }

    public static void writeGameMsg(Channel channel,int command,GeneratedMessageV3  msg){
        GameMsg gameMsg = new GameMsg();
        gameMsg.setCommand(command);
        gameMsg.setData(msg.toByteArray());
        channel.writeAndFlush(gameMsg);
    }

    static CommonProto.DynamicErrorCode buildErrorCode(int code, String msg, String... args){
        CommonProto.DynamicErrorCode.Builder builder = CommonProto.DynamicErrorCode.newBuilder();
        builder.setCode(code);
        builder.setMsg(msg);
        for(String arg : args){
            builder.addArgs(arg);
        }
        return builder.build();
    }
    
    // WebSocket连接处理器 - 修改为处理GameMsg对象
    static class WebSocketServerHandler extends SimpleChannelInboundHandler<GameMsg> {
        @Override
        protected void channelRead0(ChannelHandlerContext ctx, GameMsg msg) throws Exception {
            // 处理接收到的GameMsg对象
            System.out.println("Received WebSocket GameMsg: " + msg);
            // TODO: 实现具体业务逻辑
        }
    }
}